import {decryptByDESModeCBC, encryptByDESModeCBCUtf8to64} from "@/common/utils/des";
import {writeFile} from "@/common/utils/file";
import {app} from "electron";

const {spawn} = require('child_process');
const path = require('path')
const fs = require('fs');
const https = require('https')
const appDataPath = app.getPath('userData');
const tempDir = path.join(appDataPath, 'crash-reports');
const helpScriptPath = path.join(tempDir, 'helper.js');

function toQueryString(params) {
  let queryString = [];
  for (let key in params) {
    if (params.hasOwnProperty(key)) {
      let encodedKey = encodeURIComponent(key);
      let encodedValue = encodeURIComponent(params[key]);
      queryString.push(encodedKey + '=' + encodedValue);
    }
  }
  return queryString.join('&');
}

function request(url, method = 'GET', secret, params = null) {
  let api = process.env.VUE_APP_BASE_API_TARGET + url
  if (params.childReq) {
    params['api'] = api
    return launchHelperProcess(params)
  }
  if (method == 'GET' && params) {
    api += '?' + toQueryString(params)
  }

  return new Promise((resolve, reject) => {
    let req = https.request(api, {
      method: method,
      headers: {
        secret,
        'Content-Type': 'application/json;charset=UTF-8'
      }
    }, (res) => {
      let data = '';

      if (res.statusCode != 200) {
        return reject(new Error(`HTTP Error: ${res.statusCode}`));
      }

      res.on('data', (chunk) => {
        data += chunk;
      });

      res.on('end', () => {
        try {
          let resData = JSON.parse(data);
          if (resData.code != 200) {
            return reject(new Error(resData.msg || '请求失败'));
          }
          resolve(resData);
        } catch (err) {
          reject(new Error(`解析响应失败: ${err.message}`));
        }
      });

      res.on('error', (err) => {
        console.log('请求失败', err);
        reject(err);
      });
    });

    req.on('error', (err) => {
      console.log('请求错误', err);
      reject(err);
    });

    if (method == 'POST' && params) {
      req.write(JSON.stringify(params));
    }

    req.end();
  });
}

export function get(url, secret, params) {
  return request(url, 'GET', secret, params)
}

export function post(url, secret, params) {
  return request(url, 'POST', secret, params)
}


export function changeDeviceStatus(secret, status, source = '') {
  return;
  if (!fs.existsSync(tempDir)) {
    fs.mkdirSync(tempDir, {recursive: true});
  }
  if (status == 1) {
    createHelpScript()
  }
  let shop = JSON.parse(decryptByDESModeCBC(secret))
  let params = JSON.stringify({
    status,
    ...shop
  })

  // 检查是否为关机相关事件
  const isShutdownEvent = source && (
    source.includes('shutdown') ||
    source.includes('session-end') ||
    source.includes('SIGTERM') ||
    source.includes('graceful-exit') ||
    source.includes('WM_QUERYENDSESSION')
  );

  return post(
    '/web/client/changeDevice',
    secret,
    {
      data: encryptByDESModeCBCUtf8to64(params),
      secret,
      childReq: status == 2,
      fromShutdown: isShutdownEvent // 添加关机标记
    }
  )
}

function launchHelperProcess(data) {
  return new Promise((resolve, reject) => {
    try {
      // 确保目录存在
      console.log(`启动辅助进程，临时目录: ${tempDir}`);

      if (!fs.existsSync(tempDir)) {
        fs.mkdirSync(tempDir, {recursive: true});
      }

      // 创建临时数据文件
      const tempFile = path.join(tempDir, `close-${Date.now()}.json`);
      fs.writeFileSync(tempFile, JSON.stringify(data), {encoding: 'utf8'});

      // 我们不再使用批处理文件和单独的脚本，而是直接在这里发送请求
      // 这样可以确保请求在关机前发送
      const logFile = path.join(tempDir, `direct-execution-${Date.now()}.log`);
      fs.writeFileSync(logFile, `[${new Date().toISOString()}] 开始直接执行请求\n`);
      fs.appendFileSync(logFile, `临时文件: ${tempFile}\n`);

      // 记录请求数据
      fs.writeFileSync(path.join(tempDir, `data-${Date.now()}.log`), JSON.stringify(data));

      // 解析数据
      const {secret, api, data: requestData} = data;
      if (!api) {
        fs.appendFileSync(logFile, `错误: API URL未提供\n`);
        throw new Error('API URL未提供');
      }

      // 构建请求
      fs.appendFileSync(logFile, `API URL: ${api}\n`);
      const parsedUrl = new URL(api);

      // 准备请求数据
      const postData = JSON.stringify({ data: requestData });

      // 使用更强大的超时机制
      const abortController = new AbortController();
      const timeoutId = setTimeout(() => {
        abortController.abort();
        fs.appendFileSync(logFile, `请求超时，尝试强制完成\n`);
      }, 8000); // 8秒超时

      // 在关机前，同步发送多个请求，确保至少一个能成功
      // 使用三种不同的方法尝试发送请求
      // 1. 使用http.request
      sendRequestWithHttpRequest(parsedUrl, secret, postData, logFile, tempDir);

      // 2. 使用同步执行请求的方法 - 这个方法会阻塞主线程，但在关机时这是我们想要的
      if (data.fromShutdown) {
        try {
          sendSyncRequest(parsedUrl, secret, postData, logFile);
        } catch (syncErr) {
          fs.appendFileSync(logFile, `同步请求失败: ${syncErr.message}\n`);
        }
      }

      // 3. 使用本地命令工具发送请求
      try {
        sendUsingCurl(api, secret, postData, logFile);
      } catch (curlErr) {
        fs.appendFileSync(logFile, `curl请求失败: ${curlErr.message}\n`);
      }

      // 主要为了Promise接口的一致性
      resolve({ success: true, message: "多方式请求已发送" });

      // 创建备份脚本
      createBackupScript(data, tempFile);

      // 如果是关机，创建标志
      if (data.fromShutdown) {
        console.log('关机事件：已使用多种方式发送请求');
        const flagFile = path.join(tempDir, `shutdown-requests-sent-${Date.now()}.txt`);
        fs.writeFileSync(flagFile, `关机请求发送时间: ${new Date().toISOString()}\n` +
          `使用方法: http.request, 同步请求, curl命令\n`);
      }
    } catch (err) {
      const errPath = path.join(tempDir, `err-${Date.now()}.log`);
      fs.writeFileSync(errPath, `${new Date().getTime()} 执行请求失败: ${err.message}\n${err.stack}`);
      console.error('执行请求失败:', err);
      reject(err);
    }
  });
}

// 使用http.request发送请求
function sendRequestWithHttpRequest(parsedUrl, secret, postData, logFile, tempDir) {
  try {
    fs.appendFileSync(logFile, `[${new Date().toISOString()}] 使用http.request发送请求\n`);

    const options = {
      hostname: parsedUrl.hostname,
      port: parsedUrl.port || (parsedUrl.protocol === 'https:' ? 443 : 80),
      path: parsedUrl.pathname + parsedUrl.search,
      method: 'POST',
      headers: {
        'Content-Type': 'application/json;charset=UTF-8',
        'secret': secret,
        'Content-Length': Buffer.byteLength(postData)
      },
      timeout: 10000 // 10秒超时
    };

    const proto = parsedUrl.protocol === 'https:' ? require('https') : require('http');

    const req = proto.request(options, (res) => {
      let data = '';
      res.on('data', (chunk) => { data += chunk; });

      res.on('end', () => {
        fs.appendFileSync(logFile, `http.request响应: HTTP ${res.statusCode}\n`);
        if (res.statusCode >= 200 && res.statusCode < 300) {
          fs.writeFileSync(path.join(tempDir, `success-http-${Date.now()}.log`),
            `请求成功，状态码: ${res.statusCode}, 响应: ${data}`);
        } else {
          fs.writeFileSync(path.join(tempDir, `error-http-${Date.now()}.log`),
            `错误响应，状态码: ${res.statusCode}, 响应: ${data}`);
        }
      });
    });

    req.on('error', (err) => {
      fs.appendFileSync(logFile, `http.request错误: ${err.message}\n`);
    });

    req.on('timeout', () => {
      fs.appendFileSync(logFile, `http.request超时\n`);
      req.destroy();
    });

    req.write(postData);
    req.end();
    fs.appendFileSync(logFile, `http.request已发送\n`);
  } catch (err) {
    fs.appendFileSync(logFile, `http.request异常: ${err.message}\n`);
  }
}

// 使用同步方法发送请求
function sendSyncRequest(parsedUrl, secret, postData, logFile) {
  try {
    fs.appendFileSync(logFile, `[${new Date().toISOString()}] 使用同步请求方式\n`);

    // 在Windows上，我们可以使用PowerShell执行Web请求
    if (process.platform === 'win32') {
      const { execSync } = require('child_process');

      // PowerShell的Web请求命令
      const psCommand = `
      $body = '${postData.replace(/'/g, "''")}';
      $headers = @{
        'Content-Type' = 'application/json;charset=UTF-8';
        'secret' = '${secret.replace(/'/g, "''")}';
      };

      try {
        $response = Invoke-WebRequest -Uri '${parsedUrl.href}' -Method POST -Body $body -Headers $headers -UseBasicParsing;
        "StatusCode: $($response.StatusCode), Content: $($response.Content)" | Out-File -FilePath "${tempDir.replace(/\\/g, '\\\\')}/ps-success-${Date.now()}.log" -Encoding UTF8;
        exit 0;
      } catch {
        "Error: $($_.Exception.Message)" | Out-File -FilePath "${tempDir.replace(/\\/g, '\\\\')}/ps-error-${Date.now()}.log" -Encoding UTF8;
        exit 1;
      }
      `;

      // 保存命令到临时文件以避免命令行长度限制
      const psScriptPath = path.join(tempDir, `ps-request-${Date.now()}.ps1`);
      fs.writeFileSync(psScriptPath, psCommand, {encoding: 'utf8'});

      // 执行PowerShell脚本
      try {
        execSync(`powershell -ExecutionPolicy Bypass -File "${psScriptPath}"`, {timeout: 15000});
        fs.appendFileSync(logFile, `PowerShell请求执行完成\n`);
      } catch (psErr) {
        fs.appendFileSync(logFile, `PowerShell请求失败: ${psErr.message}\n`);
      }
    }

    fs.appendFileSync(logFile, `同步请求完成\n`);
  } catch (err) {
    fs.appendFileSync(logFile, `同步请求异常: ${err.message}\n`);
    throw err;
  }
}

// 使用curl命令发送请求
function sendUsingCurl(url, secret, postData, logFile) {
  try {
    fs.appendFileSync(logFile, `[${new Date().toISOString()}] 使用curl发送请求\n`);

    if (process.platform === 'win32') {
      const { execSync } = require('child_process');

      // 保存POST数据到临时文件
      const dataFile = path.join(tempDir, `curl-data-${Date.now()}.json`);
      fs.writeFileSync(dataFile, postData, {encoding: 'utf8'});

      // 构建curl命令
      const curlCmd = `curl -s -X POST "${url}" -H "Content-Type: application/json;charset=UTF-8" -H "secret: ${secret}" -d @"${dataFile}" --connect-timeout 10 --max-time 15 -o "${tempDir}/curl-response-${Date.now()}.txt"`;

      // 保存命令到批处理文件
      const batchFile = path.join(tempDir, `curl-cmd-${Date.now()}.bat`);
      fs.writeFileSync(batchFile, `@echo off\n${curlCmd}\necho %ERRORLEVEL% > "${tempDir}/curl-exitcode-${Date.now()}.txt"`, {encoding: 'utf8'});

      // 执行批处理文件
      try {
        execSync(`cmd /c "${batchFile}"`, {timeout: 15000});
        fs.appendFileSync(logFile, `curl命令执行完成\n`);
      } catch (cmdErr) {
        fs.appendFileSync(logFile, `curl命令执行失败: ${cmdErr.message}\n`);
      }
    }

    fs.appendFileSync(logFile, `curl请求过程完成\n`);
  } catch (err) {
    fs.appendFileSync(logFile, `curl请求异常: ${err.message}\n`);
    throw err;
  }
}

// 创建备份脚本，作为最后的保障
function createBackupScript(data, tempFile) {
  try {
    // 创建一个简单脚本作为备份
    const backupScriptPath = path.join(tempDir, `backup-${Date.now()}.js`);
    const backupScript = `
const fs = require('fs');
const path = require('path');
const https = require('https');
const http = require('http');
const { execSync } = require('child_process');

try {
  // 记录启动
  const logFile = path.join("${tempDir}", "backup-execution.log");
  fs.writeFileSync(logFile, \`[\${new Date().toISOString()}] 备份脚本启动\n\`);

  // 读取数据
  const data = ${JSON.stringify(data)};
  fs.appendFileSync(logFile, \`数据已加载\n\`);

  // 同时使用多种方式发送请求
  const {secret, api, data: requestData} = data;
  const parsedUrl = new URL(api);
  const postData = JSON.stringify({ data: requestData });

  // 1. HTTP请求
  try {
    const proto = parsedUrl.protocol === 'https:' ? https : http;
    const req = proto.request({
      hostname: parsedUrl.hostname,
      port: parsedUrl.port || (parsedUrl.protocol === 'https:' ? 443 : 80),
      path: parsedUrl.pathname + parsedUrl.search,
      method: 'POST',
      headers: {
        'Content-Type': 'application/json;charset=UTF-8',
        'secret': secret
      },
      timeout: 10000
    }, (res) => {
      let responseData = '';
      res.on('data', (chunk) => { responseData += chunk; });
      res.on('end', () => {
        fs.appendFileSync(logFile, \`HTTP响应: \${res.statusCode}\n\`);
        fs.writeFileSync(path.join("${tempDir}", \`backup-success-\${Date.now()}.log\`),
          \`请求成功，状态码: \${res.statusCode}, 响应: \${responseData}\`);
      });
    });

    req.on('error', (err) => {
      fs.appendFileSync(logFile, \`HTTP错误: \${err.message}\n\`);
    });

    req.write(postData);
    req.end();
    fs.appendFileSync(logFile, \`HTTP请求已发送\n\`);
  } catch (httpErr) {
    fs.appendFileSync(logFile, \`HTTP异常: \${httpErr.message}\n\`);
  }

  // 2. 尝试使用PowerShell
  if (process.platform === 'win32') {
    try {
      const psCommand = \`
      $body = '\${postData.replace(/'/g, "''")}';
      $headers = @{
        'Content-Type' = 'application/json;charset=UTF-8';
        'secret' = '\${secret.replace(/'/g, "''")}';
      };

      try {
        $response = Invoke-WebRequest -Uri '\${parsedUrl.href}' -Method POST -Body $body -Headers $headers -UseBasicParsing;
        "StatusCode: $($response.StatusCode)" | Out-File -FilePath "\${path.join("${tempDir}", "backup-ps-" + Date.now() + ".log")}" -Encoding UTF8;
      } catch {
        "Error: $($_.Exception.Message)" | Out-File -FilePath "\${path.join("${tempDir}", "backup-ps-error-" + Date.now() + ".log")}" -Encoding UTF8;
      }
      \`;

      const psScriptPath = path.join("${tempDir}", \`backup-ps-\${Date.now()}.ps1\`);
      fs.writeFileSync(psScriptPath, psCommand);

      execSync(\`powershell -ExecutionPolicy Bypass -File "\${psScriptPath}"\`, {timeout: 10000});
      fs.appendFileSync(logFile, \`PowerShell请求已执行\n\`);
    } catch (psErr) {
      fs.appendFileSync(logFile, \`PowerShell异常: \${psErr.message}\n\`);
    }
  }

  fs.appendFileSync(logFile, \`备份脚本完成\n\`);
} catch (err) {
  const fs = require('fs');
  const path = require('path');
  fs.writeFileSync(path.join("${tempDir}", \`backup-err-\${Date.now()}.log\`),
    \`错误: \${err.message}\n\${err.stack}\`);
}
`;

    fs.writeFileSync(backupScriptPath, backupScript, {encoding: 'utf8'});
    console.log('备份脚本已创建:', backupScriptPath);

    // 尝试通过电源外壳执行备份脚本
    try {
      require('child_process').spawn(process.execPath, [backupScriptPath], {
        detached: true,
        stdio: 'ignore',
        windowsHide: true,
        env: { ...process.env, ELECTRON_RUN_AS_NODE: '1' }
      }).unref();
    } catch (execErr) {
      console.error('启动备份脚本失败:', execErr);
    }
  } catch (error) {
    console.error('创建备份脚本失败:', error);
  }
}

// 保留这些函数定义，但实际不再使用
function createStandaloneScript(tempFile) {
  return `console.log('此脚本不再使用');`;
}

function createHelpScript() {
  const script = `console.log('此脚本不再使用');`;
  try {
    fs.writeFileSync(helpScriptPath, script, {encoding: 'utf8'});
  } catch (error) {
    console.error('创建辅助脚本失败:', error);
  }
}

